package com.example.mini_notepad.activity;

import java.io.File;
import java.io.FileInputStream;
import java.io.FileNotFoundException;
import java.io.FileOutputStream;
import java.io.IOException;
import java.text.SimpleDateFormat;
import java.util.ArrayList;
import java.util.Date;
import java.util.Locale;

import com.example.mini_notepad.R;
import com.example.mini_notepad.db.NoteContracts;
import com.example.mini_notepad.db.NoteDBAdapter;
import com.example.mini_notepad.db.NoteEntity;
import com.example.mini_notepad.util.PropertyConstants;
import com.example.mini_notepad.util.Util;

import android.media.MediaRecorder;
import android.os.Bundle;
import android.os.Environment;
import android.os.Handler;
import android.os.Looper;
import android.os.Message;
import android.support.v4.app.Fragment;
import android.util.Log;
import android.view.LayoutInflater;
import android.view.View;
import android.view.View.OnClickListener;
import android.view.ViewGroup;
import android.widget.Button;
import android.widget.TextView;
import android.widget.Toast;

public class RecordNoteFragment extends Fragment {
	private TextView tvTip;
	private TextView tvTime;
	private Button btnRec;
	private Button btnStop;
	private Button btnPlay;
	
	private int state = PropertyConstants.RECORD_STATE_STOPPED;
	private long timeCount = 0;
	
	private boolean isSDCardExist = false;
	
	private File recDir;
	private File recTempDir;
	private File recFile;
	
	private ArrayList<File> tempFiles = new ArrayList<File>();
	private int segment = 1;
	
	private MediaRecorder mediaRec;
	private TimeHandler mhandler = new TimeHandler();
	
	private NoteDBAdapter db;
	
	@Override
	public View onCreateView(LayoutInflater inflater, ViewGroup container,
            Bundle savedInstanceState){
		View rootView = inflater.inflate(R.layout.record_note_fragment, container, false);
		
		tvTip = (TextView) rootView.findViewById(R.id.tvRecTip);
		tvTime = (TextView) rootView.findViewById(R.id.tvRecTime);
		btnRec = (Button) rootView.findViewById(R.id.btnRec);
		btnStop = (Button) rootView.findViewById(R.id.btnStop);
		btnPlay = (Button) rootView.findViewById(R.id.btnPlay);
		
		btnRec.setOnClickListener(new OnButtonClickListener());
		btnStop.setOnClickListener(new OnButtonClickListener());
		btnPlay.setOnClickListener(new OnButtonClickListener());
		
		btnStop.setEnabled(false);
		//btnPlay.setEnabled(false);
		if(recFile == null){
			//btnPlay.setEnabled(false);
		}
		
		
		
		Thread timeThread = new Thread(new TimeThread());
		timeThread.start();
		
		return rootView;		
	}
	
	private class OnButtonClickListener implements OnClickListener{

		@Override
		public void onClick(View v) {
			switch(v.getId()){
			case R.id.btnRec: 
				if(btnRec.getText().toString().equals("Rec")){
					startRecording();
				}else{
					pauseRecording();
				}
				break;
			case R.id.btnStop:
				stopRecording();
				break;
			case R.id.btnPlay:
				AlarmDialogFragment dialogFragment = new AlarmDialogFragment();
				dialogFragment.show(getFragmentManager(), getTag());
				break;
			default:
				
			}			
		}		
	}
	
	private void startRecording(){
		recFile = null;
		isSDCardExist = Environment.getExternalStorageState().equals(
				android.os.Environment.MEDIA_MOUNTED);
	
		if(!isSDCardExist){
			Toast.makeText(getActivity(), "Please Insert SD Card!", Toast.LENGTH_SHORT).show();
			return;
		}else{
			recDir = new File(Environment.getExternalStorageDirectory().getAbsolutePath()+"//mini_notepad_records");
			if(!recDir.exists()){
				recDir.mkdir();
			}
			recTempDir = new File(recDir.getAbsolutePath()+"//temp_records");
			if(!recTempDir.exists()){
				recTempDir.mkdir();
			}
		}
		if(state == PropertyConstants.RECORD_STATE_STOPPED){
			timeCount = 0;
		}
		try{
			
			//Date date = new Date();
			//SimpleDateFormat dateFormat = new SimpleDateFormat ("yyyy-MM-dd");
			String prefix = (new Date()).getTime() + "_" + segment;
			File recTempFile = new File(recTempDir, prefix + ".amr");
			segment++;
			tempFiles.add(recTempFile);
			if(recTempFile.exists()){
				recTempFile.delete();
			}
			recTempFile.createNewFile();
			
			mediaRec = new MediaRecorder();
			mediaRec.setAudioSource(MediaRecorder.AudioSource.MIC);
			mediaRec.setOutputFormat(MediaRecorder.OutputFormat.DEFAULT);
			mediaRec.setAudioEncoder(MediaRecorder.AudioEncoder.DEFAULT);
			mediaRec.setOutputFile(recTempFile.getAbsolutePath());
			
			mediaRec.prepare();
			mediaRec.start();
			
			state = PropertyConstants.RECORD_STATE_RECORDING;
			
			tvTip.setText("Recording...");
			btnStop.setEnabled(true);
			btnRec.setText("Pause");
		} catch(IOException e){
			Toast.makeText(getActivity(), "Error Occured.", Toast.LENGTH_SHORT).show();
			Log.e("Rec", "Throwing IOException when Recording.", e);
		}
	}
	
	private void pauseRecording(){
		state = PropertyConstants.RECORD_STATE_PAUSED;
		if(mediaRec != null){
			mediaRec.stop();
			mediaRec.release();
			mediaRec = null;
		}
		btnRec.setText("Rec");
	}
	
	private void stopRecording(){
		if(mediaRec != null){
			mediaRec.stop();
			mediaRec.release();
			mediaRec = null;
		}
		
		state = PropertyConstants.RECORD_STATE_STOPPED;
		
		tvTip.setText("Rec is stopped...");
		btnStop.setEnabled(false);
		btnRec.setText("Rec");
		
		recFile = new File(recDir, (new Date()).getTime()+".amr");
		if(!recFile.exists()){
			try{
				recFile.createNewFile();
			}catch(IOException e){
				e.printStackTrace();
			}
		}
		
		FileOutputStream outputStream = null;
		try{
			outputStream = new FileOutputStream(recFile);
		}catch(IOException e){
			e.printStackTrace();
		}
		
		for(File f : tempFiles){
			FileInputStream inputStream = null;
			try {
				inputStream = new FileInputStream(f);
				byte[] tempBytes = new byte[inputStream.available()];
				
				while(inputStream.read(tempBytes) != -1){
					outputStream.write(tempBytes);
				}
				outputStream.flush();
				inputStream.close();
			} catch (FileNotFoundException e) {
				// TODO Auto-generated catch block
				e.printStackTrace();
			} catch (IOException e) {
				// TODO Auto-generated catch block
				e.printStackTrace();
			} finally{
				inputStream = null;
				f.delete();
			}				
		}
		if(outputStream != null){
			try {
				outputStream.close();
			} catch (IOException e) {
				// TODO Auto-generated catch block
				e.printStackTrace();
			} finally{
				outputStream = null;
			}
		}
		
		tempFiles.clear();
		segment = 1;
		
		if(!saveRecordToDB()){
			Toast.makeText(getActivity(), "Failed to save record...", Toast.LENGTH_SHORT).show();
			return;
		}
		
		
	}
	
	private void playAudio(){
		
	}
	
	private boolean saveRecordToDB(){
		if(recFile == null){
			return false;
		}
		NoteEntity rec = new NoteEntity();		
		rec.setCreateTime(Util.getTimeString(new Date()));
		rec.setType(PropertyConstants.NOTE_TYPE_RECORD);
		
		db = new NoteDBAdapter(getActivity());
		db.open();
		String title = rec.getCreateTime().substring(0, 10);
		int numOfExistedNotes = db.getNumOfNotesInTheSameDay(PropertyConstants.NOTE_TYPE_RECORD, title);
		
		if(numOfExistedNotes >= 1){
			title = rec.getCreateTime().substring(0, 10) + " (" + numOfExistedNotes + 1 +")";
			if(numOfExistedNotes == 1){
				db.updateNotes(PropertyConstants.NOTE_TYPE_RECORD, title, title + " (1)");				
			}
		}
		rec.setTitle(title);
		rec.setNotifyTime("");
		rec.setContent(recFile.getAbsolutePath()); // for record note, content is used to save the file path of the audio.
		rec.setDuration(timeCount);
		
		db.insertNote(rec);
		db.close();
		return true;
	}
	
	private class TimeThread implements Runnable{

		@Override
		public void run() {
			// TODO Auto-generated method stub
			while(true){
				if(state == PropertyConstants.RECORD_STATE_RECORDING){
					++timeCount;
					Message msg = new Message();
					msg.what = PropertyConstants.MESSAGE_CODE_TIME;
					mhandler.sendMessage(msg);
				}
				try {
					Thread.sleep(1000);
				} catch (InterruptedException e) {
					// TODO Auto-generated catch block
					e.printStackTrace();
				}
			}
		}
		
	}
	
	private class TimeHandler extends Handler{
		public TimeHandler(){}
		public TimeHandler(Looper L){
			super(L);
		}
		@Override
		public void handleMessage(Message msg){
			super.handleMessage(msg);
			if(msg.what == PropertyConstants.MESSAGE_CODE_TIME){
				long mins = timeCount/60;
				long secs = timeCount%60;
				String strMins = (mins >= 10) ? mins+"" : "0"+mins;
				String strSecs = (secs >= 10) ? secs+"" : "0"+secs;
				tvTime.setText(strMins + ":" + strSecs);
			}
		}
		
	}

}
